﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Diagnostics;

namespace MemoryViewControl
{
  public partial class MemoryViewContainerControl : UserControl
  {

    private MemorySpace memorySpace = new MemorySpace();

    public MemorySpace MemorySpace { get { return memorySpace; } }
    public MemoryHeatMapControl MemoryHeatMapControl { get { return memoryHeatMapControl1; } }
    public MemoryHexEditorControl MemoryHexEditorControl { get { return memoryHexEditorControl1; } }
    
    public MemoryViewContainerControl()
    {
      InitializeComponent();
      //this.SetStyle(ControlStyles.Selectable, true);

      memoryHeatMapControl1.MemorySpace = memorySpace;

      memoryHexEditorControl1.MemorySpace = memorySpace;

      memorySpace.PropertyChanged += new PropertyChangedEventHandler(MemorySpace_PropertyChanged);
    }

    private void MemorySpace_PropertyChanged(object sender, PropertyChangedEventArgs args)
    {
      switch (args.PropertyName)
      {
        default:
          break;
      }
    }

    private void MemoryHexEditorControl_PropertyChanged(object sender, PropertyChangedEventArgs args)
    {
      switch (args.PropertyName)
      {
        case "Columns":
          comboBoxColumns.SelectedIndex = comboBoxColumns.Items.IndexOf(memoryHexEditorControl1.Columns.ToString());
          break;

        case "Grouping":
          comboBoxGrouping.SelectedIndex = comboBoxGrouping.Items.IndexOf(memoryHexEditorControl1.Grouping.ToString());
          break;

        case "RenderHiddenBytes":
          checkBoxRenderHidden.Checked = memoryHexEditorControl1.RenderHiddenBytes;
          break;

        case "RenderInvalidBytes":
          checkBoxRenderInvalid.Checked = memoryHexEditorControl1.RenderInvalidBytes;
          break;

        default:
          break;
      }
    }

    private void MemoryHeatMapControl_PropertyChanged(object sender, PropertyChangedEventArgs args)
    {
      switch (args.PropertyName)
      {
        case "HeatMapWidth":
          comboBoxHeatMapWidth.SelectedIndex = comboBoxHeatMapWidth.Items.IndexOf(memoryHeatMapControl1.HeatMapWidth.ToString());
          break;

        default:
          break;
      }
    }

    #region Drawing

    private void UpdateHexViewOffset(uint offset)
    {
      memoryHexEditorControl1.Offset = offset;

      textBoxOffset.Text = "0x" + memoryHexEditorControl1.Offset.ToString("X" + memorySpace.AddressNibbles.ToString());
      textBoxOffset.Invalidate();
    }

    #endregion



    #region Handling Events

    private void textBoxOffset_KeyPress(object sender, KeyPressEventArgs e)
    {
      if (e.KeyChar == (char)Keys.Return)
      {
        e.Handled = true;
        string text = textBoxOffset.Text;
        uint offset;

        if (text.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
        {
          text = text.Substring(2);
          if (uint.TryParse(text, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out offset))
          {
            UpdateHexViewOffset(offset);
          }
        }
        else
        {
          if (uint.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out offset))
          {
            UpdateHexViewOffset(offset);
          }
        }
      }
    }

    private void comboBoxGrouping_SelectedIndexChanged(object sender, EventArgs e)
    {
      int grouping;
      int.TryParse(comboBoxGrouping.Text, out grouping);
      memoryHexEditorControl1.Grouping = grouping;
    }

    private void comboBoxColumns_SelectedIndexChanged(object sender, EventArgs e)
    {
      int columns;
      int.TryParse(comboBoxColumns.Text, out columns);
      memoryHexEditorControl1.Columns = columns;
    }

    private void comboBoxHeatMapWidth_SelectedIndexChanged(object sender, EventArgs e)
    {
      int heatMapWidth;
      int.TryParse(comboBoxHeatMapWidth.Text, out heatMapWidth);
      memoryHeatMapControl1.HeatMapWidth = heatMapWidth;
    }

    private void checkBoxRenderInvalid_CheckedChanged(object sender, EventArgs e)
    {
      memoryHexEditorControl1.RenderInvalidBytes = checkBoxRenderInvalid.Checked;
    }

    private void checkBoxRenderHidden_CheckedChanged(object sender, EventArgs e)
    {
      memoryHexEditorControl1.RenderHiddenBytes = checkBoxRenderHidden.Checked;
    }

    #endregion

    private void memoryHexEditorControl1_HoverAddressChanged(object sender, MemoryHexEditorControl.HoverAddressChangedEventArgs e)
    {
      if (e.valid)
      {
        this.toolStripStatusLabelOffset.Text = string.Format("0x{0:X8}", e.address);
      }
      else
      {
        this.toolStripStatusLabelOffset.Text = "0x00000000";
      }

      toolStripStatusLabelSelection.Text = string.Format("0x{0:X8}-0x{1:X8} (0x{2:X2})",
        memoryHexEditorControl1.SelectionStart, memoryHexEditorControl1.SelectionStart + memoryHexEditorControl1.SelectionLength, memoryHexEditorControl1.SelectionLength);
    }

    private void MemoryViewContainerControl_Load(object sender, EventArgs e)
    {
      comboBoxColumns.SelectedIndex = comboBoxColumns.Items.IndexOf(memoryHexEditorControl1.Columns.ToString());

      comboBoxGrouping.SelectedIndex = comboBoxGrouping.Items.IndexOf(memoryHexEditorControl1.Grouping.ToString());

      checkBoxRenderHidden.Checked = memoryHexEditorControl1.RenderHiddenBytes;

      checkBoxRenderInvalid.Checked = memoryHexEditorControl1.RenderInvalidBytes;

      comboBoxHeatMapWidth.SelectedIndex = comboBoxHeatMapWidth.Items.IndexOf(memoryHeatMapControl1.HeatMapWidth.ToString());
    }
  }
}
